package com.engine.downcustomfile.uitil;

import com.alibaba.fastjson.JSONObject;
import com.api.doc.detail.service.DocSaveService;
import com.engine.downcustomfile.vo.AgendaItem;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import weaver.conn.RecordSet;
import weaver.file.ImageFileManager;
import weaver.general.BaseBean;
import weaver.hrm.User;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Administrator
 */
public class GenerateWordDocument {
    private static final String[] CHINESE_NUMBERS = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};

    /**
     * 根据requestid拿到表明，及表对应的明细。
     * @param requestId
     * @return
     */
    public static void createDocByRequestId(String requestId) {
        BaseBean baseBean = new BaseBean();
        String workflowId = WorkflowInfoUtil.getWrokflowId(requestId);
        String docCategory = WorkflowInfoUtil.getCategory(workflowId);
        String tableName = WorkflowInfoUtil.getTableName(workflowId);
        String detailTable = tableName + "_dt1";
        baseBean.writeLog("requestId_：" + requestId);
        baseBean.writeLog("workflowId_：" + workflowId);
        baseBean.writeLog("docCategory_：" + docCategory);
        baseBean.writeLog("tableName_：" + tableName);

        RecordSet rs = new RecordSet();
        List<Map<String, String>> tableData = WorkflowInfoUtil.getData(rs,
                "select id,hymc,hylxwbzd,gdlxr,zs,hynf,sj,dd,zc,hyqc,hylx,cx,qj,bz from " + tableName + " where requestid = ?",requestId);

        baseBean.writeLog("getDatatableNameSql_：" + "select id,hymc,hylxwbzd,gdlxr,zs,hynf,sj,dd,zc,hyqc,hylx,cx,qj,bz from " + tableName + " where requestid = ?");

        for (Map<String, String> itemData : tableData) {
            String id = itemData.getOrDefault("id", "");
            List<Map<String, String>> detailData = WorkflowInfoUtil.getData(rs,
                    "select hymc,hbbm,lxbm,tlnr,sfyxzsh from " + detailTable + " where mainid = ?", id);

            baseBean.writeLog("getDetailSql_：" + "select hymc,hbbm,lxbm,tlnr,sfyxzsh from " + detailTable + " where requestid = ?");

            ArrayList<AgendaItem> agendaItems = new ArrayList<>();
            for (Map<String, String>  detailItem: detailData) {
                AgendaItem agendaItem = new AgendaItem();

                String dhymc = detailItem.getOrDefault("hymc", "");
                String hbbm = detailItem.getOrDefault("hbbm", "");
                String lxbm = detailItem.getOrDefault("lxbm", "");
                String tlnr = detailItem.getOrDefault("tlnr", "");
                String meetName = getNameById(dhymc);
                agendaItem.setTitle(meetName);
                String postDeptNames = getDeptByIds(hbbm);
                agendaItem.setPosition(postDeptNames);
                String observerDeptNames = getDeptByIds(lxbm);
                agendaItem.setObserver(observerDeptNames);
                String content = getContentName(tlnr);
                agendaItem.setContent(content);
                agendaItems.add(agendaItem);
            }
            String title = itemData.getOrDefault("hymc", "");
            String time = itemData.getOrDefault("sj", "");
            String dd = itemData.getOrDefault("dd", "");
            String location = getLocationString(dd);
            String hostId = itemData.getOrDefault("zc", "");
            String host = getHrmString(hostId);
            String cx = itemData.getOrDefault("cx", "");
            String attendees = getHrmString(cx);
            String qj = itemData.getOrDefault("qj", "");
            String absentees = getHrmString(qj);
            String bz = itemData.getOrDefault("bz", "");
            int docId = 0;
            try {
                baseBean.writeLog("title_"+title+"_time_"+time+"_location_"+location+"_host_"+host+"_attendees_"+attendees+"_absentees_"+absentees+"_bz_"+bz);
                baseBean.writeLog("agendaItems___" + JSONObject.toJSONString(agendaItems));
                docId = generateDocument(title, time, location, host, attendees, absentees, agendaItems, bz, docCategory);
                baseBean.writeLog("生成文档成功" + docId);
            } catch (Exception e) {
                e.printStackTrace();
            }
            doSaveDocId(docId, tableName, requestId);
        }

    }

    private static String getContentName(String tlnr) {
        RecordSet recordSet = new RecordSet();
        String name = "";
        boolean b = recordSet.executeQuery("select docsubject from docdetail where id = ?", tlnr);
        if (b && recordSet.next()){
            name = recordSet.getString("docsubject");
        }
        return name;
    }

    private static String getDeptByIds(String hbbm) {
        String[] hbbmArr = hbbm.split(",");
        RecordSet recordSet = new RecordSet();
        String dept = "";
        for (String lo : hbbmArr) {
            boolean b = recordSet.executeQuery("select DEPARTMENTMARK from hrmdepartment where id = ?", lo);
            if (b && recordSet.next()){
                if (dept.isEmpty()){
                    dept = recordSet.getString("DEPARTMENTMARK");
                }else{
                    dept += "、"+recordSet.getString("DEPARTMENTMARK");
                }
            }
        }
        return dept;
    }

    private static String getNameById(String dhymc) {
        RecordSet recordSet = new RecordSet();
        String name = "";
        boolean b = recordSet.executeQuery("select nshytmc from uf_sbzhlhyglhyhztz where id = ?", dhymc);
        if (b && recordSet.next()){
                name = recordSet.getString("nshytmc");
        }
        return name;
    }

    private static void doSaveDocId(int docId, String tableName, String requestId) {
        String updateSql = "update " + tableName + " set zw = ? where requestid = ?";
        RecordSet recordSet = new RecordSet();
        recordSet.executeUpdate(updateSql, docId, requestId);
    }




    private static String getLocationString(String locations) {
        String[] locationArr = locations.split(",");
        RecordSet recordSet = new RecordSet();
        String location = "";
        for (String lo : locationArr) {
            boolean b = recordSet.executeQuery("select name from meetingroom where id = ?", lo);
            if (b && recordSet.next()){
                if (location.isEmpty()){
                    location = recordSet.getString("name");
                }else{
                    location += "、"+recordSet.getString("name");
                }
            }
        }
        return location;
    }

    private static String getHrmString(String hrms) {
        String[] hrmArr = hrms.split(",");
        RecordSet recordSet = new RecordSet();
        String hrmName = "";
        for (String hrm : hrmArr) {
            boolean b = recordSet.executeQuery("select lastname from hrmresource where id = ?", hrm);
            if (b && recordSet.next()){
                if (hrmName.isEmpty()){
                    hrmName = recordSet.getString("lastname");
                }else{
                    hrmName += "、"+recordSet.getString("lastname");;
                }
            }
        }
        return hrmName;
    }

    public static int generateDocument(String title,String time, String location, String host, String attendees,
                                        String absentees, List<AgendaItem> agendaItems, String note,String docCategory)
            throws Exception {
        BaseBean baseBean = new BaseBean();
        XWPFDocument document = new XWPFDocument();
        // 设置页面边距（兼容低版本 Apache POI）无法兼容在不可用
        //setPageMargins(document, 1.75, 2.5, 2.5, 2.5);

        //设置标题样式
        setTitleParagraph(document,title);
        baseBean.writeLog("setTitleParagraph_____");

        //时间行
        setTimeParagraph(document,time);
        baseBean.writeLog("setTimeParagraph_____");

        // 地点部分样式设置
        setLocationParagraph(document,location);
        baseBean.writeLog("setLocationParagraph_____");

        // 主持部分样式设置
        setHostParagraph(document,host);
        baseBean.writeLog("setHostParagraph_____");

        // 参会人员部分 - 标题行
        setAttendeesTitleParagraph(document);
        baseBean.writeLog("setAttendeesTitleParagraph_____");

        // 参会人员部分 - “出席” 行
        if (!attendees.isEmpty()) {
            setAttendeesPresentParagraph(document,attendees);
            baseBean.writeLog("setAttendeesPresentParagraph_____");

        }

        // 参会人员部分 - “请假” 行（如果有请假人员）
        if (!absentees.isEmpty()) {
            setAttendeesAbsentParagraph(document,absentees);
            baseBean.writeLog("setAttendeesAbsentParagraph_____");

        }

        //议程安排标题
        setMettingParagraph(document);
        baseBean.writeLog("setMettingParagraph_____");
        int i = 0;
        // 议程安排部分样式设置
        for (AgendaItem agenda : agendaItems) {
            i++;
            setAgendaParagraph(document, agenda, i);
            baseBean.writeLog("setAgendaParagraph_____" + i + "____" + JSONObject.toJSONString(agenda));
        }

        // 备注标题行
        setNoteParagraph(document);
        //备注可能出现换行
        String[] parts = note.split("(?i)<br\\s*/?>");
        for (int j = 0; j < parts.length; j++) {
            String part = parts[j];
            setNoteParagraph(document, part);
        }
        baseBean.writeLog("setNoteParagraph_____");

        byte[] bytes = documentToByteArray(document);

        int docId = doSaveDoc(bytes, title + "_会议记录.doc", docCategory);
        return docId;
    }

    private static int doSaveDoc(byte[] bytes,  String fileName,String docCategory) {
        ImageFileManager imageFileManager = new ImageFileManager();
        imageFileManager.resetParameter();
        imageFileManager.setData(bytes);
        imageFileManager.setImagFileName(fileName);
        int imgFileId = imageFileManager.saveImageFile();
        DocSaveService docSaveService = new DocSaveService();
        int docid = -1;
        try {
            //生成文档附件 目录id 文件id  用户  返回文档id
            docid = docSaveService.accForDoc(Integer.parseInt(docCategory), imgFileId, new User(1));
        } catch (Exception e) {
        }
        return docid;
    }

    public static byte[] documentToByteArray(XWPFDocument document) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            // 将文档内容写入输出流
            document.write(outputStream);
            // 转换为字节数组
            return outputStream.toByteArray();
        }
    }

    private static void setNoteParagraph(XWPFDocument document) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 6,18, -1, 1.5);
        setXwpfRun("六、备注：","黑体",16,false,xwpfParagraph);
    }

    private static void setNoteParagraph(XWPFDocument document, String note) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 6,18, -1, 1.5);
        setXwpfRun(note, "仿宋_GB2312", 16, false, xwpfParagraph);
    }

    private static void setAgendaParagraph(XWPFDocument document, AgendaItem agenda, int i) {
        String bi = toChineseNumberWithBrackets(i);
        setDeatilTitle(document, bi + agenda.getTitle());
        setDeatilInfoPosition(document, "1."+agenda.getPosition() + "汇报");
        //+agenda.getContent()
        setDeatilInfoContent(document, "2.讨论");
        setDeatilInfoObserver(document, "列席：" + agenda.getObserver());

    }

    private static void setDeatilInfoContent(XWPFDocument document, String docSubjects) {
        setDeatilInfoPosition(document, docSubjects);
    }

    private static String getDocSubject(String docSubjects) {
        String[] docSubjectArr = docSubjects.split(",");
        RecordSet recordSet = new RecordSet();
        String docSubjectNames = "";
        for (String docSubject : docSubjectArr) {
            boolean b = recordSet.executeQuery("select docsubject from docdetail where id = ?", docSubject);
            if (b && recordSet.next()){
                if (docSubjectNames.equals("")){
                    docSubjectNames = recordSet.getString("docsubject");
                }else{
                    docSubjectNames += "、" + recordSet.getString("docsubject");
                }
            }
        }
        return docSubjectNames;
    }

    private static XWPFParagraph createParagraph(XWPFDocument document) {
        XWPFParagraph agendaParagraph = document.createParagraph();
        agendaParagraph.setSpacingBefore(6);
        agendaParagraph.setSpacingAfter(6);
        setLineSpacing(agendaParagraph, 1.5);
        return agendaParagraph;
    }

    private static void setDeatilInfoObserver(XWPFDocument document, String observer) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, -1,-1, -1, -1);
        setXwpfRun(observer,"楷体_GB2312",16,false,xwpfParagraph);
    }

    private static void setDeatilInfoPosition(XWPFDocument document, String position) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, -1,-1, -1, -1);
        setXwpfRun(position,"仿宋_GB2312",16,false,xwpfParagraph);
    }

    private static void setDeatilTitle(XWPFDocument document, String title) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, -1,-1, -1, -1);
        setXwpfRun(title,"楷体_GB2312",16,true,xwpfParagraph);
    }

    private static void setAttendeesAbsentParagraph(XWPFDocument document,String absentees) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 0,6, -1, 1.5);
        setXwpfRun("请  假：","楷体_GB2312",16,true,xwpfParagraph);
        setXwpfRun(absentees, "仿宋_GB2312", 16, false, xwpfParagraph);
    }

    private static void setAttendeesPresentParagraph(XWPFDocument document, String attendees) {

        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 0,3, -1, 1.5);
        setXwpfRun("出  席：","楷体_GB2312",16,true,xwpfParagraph);
        setXwpfRun(attendees, "仿宋_GB2312", 16, false, xwpfParagraph);

    }

    private static void setMettingParagraph(XWPFDocument document) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 6,12, -1, 1.5);
        setXwpfRun("五、议程安排","黑体",16,false,xwpfParagraph);
    }

    private static void setAttendeesTitleParagraph(XWPFDocument document) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 6,12, -1, 1.5);
        setXwpfRun("四、参会人员","黑体",16,false,xwpfParagraph);
    }

    private static void setHostParagraph(XWPFDocument document, String host) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 6,6, -1, 1.5);
        setXwpfRun("三、主持：","黑体",16,false,xwpfParagraph);
        setXwpfRun(host,"仿宋_GB2312",16,false,xwpfParagraph);
    }

    private static void setLocationParagraph(XWPFDocument document,String location) {

        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 6,6, -1, 1.5);
        setXwpfRun("二、地点：","黑体",16,false,xwpfParagraph);
        setXwpfRun(location,"仿宋_GB2312",16,false,xwpfParagraph);
    }


    private static void setLineSpacing(XWPFParagraph paragraph, double lineSpacing) {
        CTPPr ppr = paragraph.getCTP().getPPr();
        if (ppr == null) {
            ppr = paragraph.getCTP().addNewPPr();
        }
        CTSpacing spacing = ppr.isSetSpacing() ? ppr.getSpacing() : ppr.addNewSpacing();
        spacing.setLine(BigInteger.valueOf((long) (lineSpacing * 240)));
        spacing.setLineRule(STLineSpacingRule.Enum.forString("auto"));
    }


    private static void setTitleParagraph(XWPFDocument document,String title) {
        XWPFParagraph xwpfParagraph = setParagraph(document, ParagraphAlignment.CENTER, 400, 50, -1, 150, 1.5);
        setXwpfRun(title,"方正小标宋简体",18,false,xwpfParagraph);
    }


    private static void setTimeParagraph(XWPFDocument document,String time) {
        XWPFParagraph xwpfParagraph = setParagraph(document, null,400, 12,6, -1, 1.5);
        setXwpfRun("一、时间：","黑体",16,false,xwpfParagraph);
        setXwpfRun(time,"仿宋_GB2312",16,false,xwpfParagraph);
    }

    /**
     *
     * @param document
     * @param alignment  是否居中
     * @param indentationFirstLine
     * @param spacingBefore 行上距离
     * @param spaceingAfter 下行距离
     * @param spacingAfterLines
     * @param lineSpacing 行距
     * @return
     */
    private static XWPFParagraph setParagraph(
            XWPFDocument document,
            ParagraphAlignment alignment,
            int indentationFirstLine,
            int spacingBefore,
            int spaceingAfter,
            int spacingAfterLines,
            double lineSpacing
    ) {
        // 标题样式设置
        XWPFParagraph paragraph = document.createParagraph();
        if (alignment != null){
            paragraph.setAlignment(alignment);
        }

        if (indentationFirstLine >= 0 ) {
            paragraph.setIndentationFirstLine(indentationFirstLine);
        }

        if (spacingBefore >= 0) {
            paragraph.setSpacingBefore(spacingBefore);
        }

        if (spaceingAfter >= 0) {
            paragraph.setSpacingAfter(spaceingAfter);
        }

        if (spacingAfterLines >= 0) {
            paragraph.setSpacingAfterLines(spacingAfterLines);
        }

        if (lineSpacing >= 0) {
            setLineSpacing(paragraph, lineSpacing);
        }

        return paragraph;
    }

    //设置字体的内容
    private static void setXwpfRun(
            String title,
            String fontFamily,
            int fontSize,
            boolean isBold,
            XWPFParagraph paragraph
    ) {
        // 标题样式设置
        XWPFRun xwpfRun = paragraph.createRun();
        if (!StringUtils.isEmpty(title)) {
            xwpfRun.setText(title);
        }
        if (!StringUtils.isEmpty(fontFamily)) {
            xwpfRun.setFontFamily(fontFamily);
        }
        if (fontSize >= 0) {
            xwpfRun.setFontSize(fontSize);
        }
        xwpfRun.setBold(isBold);
    }

    /**
     * 生成中文序号（带括号），如 1 → （一）
     */
    public static String toChineseNumberWithBrackets(int number) {
        if (number <= 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder("（");

        if (number <= 10) {
            // 1-10 直接映射
            sb.append(CHINESE_NUMBERS[number - 1]);
        } else if (number < 20) {
            // 11-19：十 + 数字
            sb.append("十").append(CHINESE_NUMBERS[number - 11]);
        } else if (number == 20) {
            // 20：二十
            sb.append("二十");
        } else {
            // 21+：十位数字 + 十 + 个位数字
            int tens = number / 10;
            int ones = number % 10;

            if (tens > 0) {
                if (tens != 1) { // 非“一十”，直接用数字
                    sb.append(CHINESE_NUMBERS[tens - 1]);
                }
                sb.append("十");
            }

            if (ones > 0) {
                sb.append(CHINESE_NUMBERS[ones - 1]);
            }
        }

        sb.append("）");
        return sb.toString();
    }

}